`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    09:30:30 07/22/2013 
// Design Name: 
// Module Name:    field_splinter 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module fs_test2(
    rst_n,
    clk,
    valid,
    data_in,
    msg_end_1_2,
    ready,
    data_out0,
    data_out1,
    sel0,
    sel1
    );


    parameter S_PMAP = 2'b01;
    parameter S_FIELD = 2'b10;

    input rst_n;
    input clk;
    input valid;
    input [63:0] data_in;
    input msg_end_1_2;
    
    
    output ready;
    output [63:0] data_out0;
    output [63:0] data_out1;
    output [49:0] sel0;
    output [49:0] sel1;
    
    reg [63:0] data_out0;
    reg [63:0] data_out0_next;
    
    reg [63:0] data_out1;
    reg [63:0] data_out1_next;
    
    //reg [3:0] ready;
    
    wire [3:0] total;
    
    reg [7:0] data [0:15];
    
    reg [3:0] head;
    reg [3:0] head_next;
    reg [3:0] tail;
    
    reg set;
    reg [49:0] pmap_in;
    reg [1:0] id_jump;
    reg [1:0] id_jump_next;
    
    reg [1:0] state;
    reg [1:0] state_next;
    
    assign total = tail - head;
    
    assign ready = (total <= 5'd8);
    
    
    integer i;
    
    always @(negedge rst_n, posedge clk)
    begin
        if(~rst_n)
        begin
            for(i=0;i<16;i=i+1)
                data[i] <= 8'b0;
        end
        else if(valid && ready)
        begin
            //$display("tail : %d\n", tail);
            data[tail+4'd0] <= data_in[7:0];
            data[tail+4'd1] <= data_in[15:8];
            data[tail+4'd2] <= data_in[23:16];
            data[tail+4'd3] <= data_in[31:24];
            data[tail+4'd4] <= data_in[39:32];
            data[tail+4'd5] <= data_in[47:40];
            data[tail+4'd6] <= data_in[55:48];
            data[tail+4'd7] <= data_in[63:56];
        end
    end
    
    always @(negedge rst_n, posedge clk)
    begin
        if(~rst_n)
            tail <= 4'b0;
        else if(msg_end_1_2)
            tail <= 4'b0;
        else if( ready && valid )
            tail <= tail + 4'd8;
    end
    
    always @(negedge rst_n, posedge clk)
    begin
        if(~rst_n)
            head <= 4'b0;
        else if(msg_end_1_2)
            head <= 4'd0;
        else
            head <= head_next;
    end
    
    always @(negedge rst_n, posedge clk)
    begin
        if(~rst_n)
            data_out0 <= 64'b0;
        else
            data_out0 <= data_out0_next;
    end
    
    always @(negedge rst_n, posedge clk)
    begin
        if(~rst_n)
            data_out1 <= 64'b0;
        else
            data_out1 <= data_out1_next;
    end
    
    always @(negedge rst_n, posedge clk)
    begin
        if(~rst_n)
            state <= S_PMAP;
        else
            state <= state_next;
    end
    always @(negedge rst_n, posedge clk)
    begin
        if(~rst_n)
            id_jump <= 2'b0;
        else
            id_jump <= id_jump_next;
    end
    
    always @(msg_end_1_2, state, head, head_next)
    begin
        if(msg_end_1_2)
            state_next = S_PMAP;
        else
        begin
            case(state)
                S_PMAP:
                    if(head_next != head)
                        state_next = S_FIELD;
                    else
                        state_next = S_PMAP;
                S_FIELD:
                    state_next = state;
                default:
                    state_next = state;
            endcase
        end
    end
    
    always @( head, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7],
              data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15], total, state )
    begin
        case(state)
            S_PMAP:
            begin
                data_out0_next = 64'b0;
                data_out1_next = 64'b0;
                id_jump_next = 2'd0;
                if(total >= 1 && data[head][7])
                begin
                    set=1'b1;
                    head_next = head+4'd1;
                    pmap_in[49:7] = 43'b0;
                    for(i=0;i<=6;i=i+1)
                        pmap_in[6-i] = data[head][i];
                end
                else if(total >= 2 && data[head+4'd1][7])
                begin
                    set=1'b1;
                    head_next = head+4'd2;
                    pmap_in[49:14] = 36'b0;
                    for(i=0;i<7;i=i+1)
                    begin
                        pmap_in[6-i] = data[head][i];
                        pmap_in[13-i] = data[head+4'd1][i];
                    end
                end
                else if(total >= 3 && data[head+4'd2][7])
                begin
                    set=1'b1;
                    head_next = head+4'd3;
                    pmap_in[49:21] = 29'b0;
                    for(i=0;i<7;i=i+1)
                    begin
                        pmap_in[6-i] = data[head][i];
                        pmap_in[13-i] = data[head+4'd1][i];
                        pmap_in[20-i] = data[head+4'd2][i];
                    end
                end
                else if(total >= 4 && data[head+4'd3][7])
                begin
                    set=1'b1;
                    head_next = head+4'd4;
                    pmap_in[49:28] = 22'b0;
                    for(i=0;i<7;i=i+1)
                    begin
                        pmap_in[6-i] = data[head][i];
                        pmap_in[13-i] = data[head+4'd1][i];
                        pmap_in[20-i] = data[head+4'd2][i];
                        pmap_in[27-i] = data[head+4'd3][i];
                    end
                end
                else if(total >= 5 && data[head+4'd4][7])
                begin
                    set=1'b1;
                    head_next = head+4'd5;
                    pmap_in[49:35] = 15'b0;
                    for(i=0;i<7;i=i+1)
                    begin
                        pmap_in[6-i] = data[head][i];
                        pmap_in[13-i] = data[head+4'd1][i];
                        pmap_in[20-i] = data[head+4'd2][i];
                        pmap_in[27-i] = data[head+4'd3][i];
                        pmap_in[34-i] = data[head+4'd4][i];
                    end
                end
                else if(total >= 6 && data[head+4'd5][7])
                begin
                    set=1'b1;
                    head_next = head+4'd6;
                    pmap_in[49:42] = 8'b0;
                    for(i=0;i<7;i=i+1)
                    begin
                        pmap_in[6-i] = data[head][i];
                        pmap_in[13-i] = data[head+4'd1][i];
                        pmap_in[20-i] = data[head+4'd2][i];
                        pmap_in[27-i] = data[head+4'd3][i];
                        pmap_in[34-i] = data[head+4'd4][i];
                        pmap_in[41-i] = data[head+4'd5][i];
                    end
                end
                else if(total >= 7 && data[head+4'd6][7])
                begin
                    set=1'b1;
                    head_next = head+4'd7;
                    pmap_in[49] = 1'b0;
                    for(i=0;i<7;i=i+1)
                    begin
                        pmap_in[6-i] = data[head][i];
                        pmap_in[13-i] = data[head+4'd1][i];
                        pmap_in[20-i] = data[head+4'd2][i];
                        pmap_in[27-i] = data[head+4'd3][i];
                        pmap_in[34-i] = data[head+4'd4][i];
                        pmap_in[41-i] = data[head+4'd5][i];
                        pmap_in[48-i] = data[head+4'd6][i];
                    end
                end
                else if(total >= 8 && data[head+4'd7][7])
                begin
                    set=1'b1;
                    head_next = head+4'd8;
                    pmap_in[49] = data[head+4'd7][6];
                    for(i=0;i<7;i=i+1)
                    begin
                        pmap_in[6-i] = data[head][i];
                        pmap_in[13-i] = data[head+4'd1][i];
                        pmap_in[20-i] = data[head+4'd2][i];
                        pmap_in[27-i] = data[head+4'd3][i];
                        pmap_in[34-i] = data[head+4'd4][i];
                        pmap_in[41-i] = data[head+4'd5][i];
                        pmap_in[48-i] = data[head+4'd6][i];
                    end
                end
                else
                begin
                    set=1'b0;
                    head_next = head;
                    pmap_in = 50'b0;
                end
            end
            S_FIELD:
            begin
                set=1'b0;
                pmap_in = 50'b0;
                if(total >= 1 && data[head][7])
                begin
                    //head_next = head+4'd1;
                    data_out0_next = {56'b0,data[head]};
                    if(total >= 2 && data[head+4'd1][7])
                    begin
                        id_jump_next = 2'd2;
                        head_next = head+4'd2;
                        data_out1_next = {56'b0,data[head+4'd1]};
                    end
                    else if(total >= 3 && data[head+4'd2][7])
                    begin
                        id_jump_next = 2'd2;
                        head_next = head+4'd3;
                        data_out1_next = {48'b0,
                                          data[head+4'd1],
                                          data[head+4'd2]};
                    end
                    
                    else if(total >= 4 && data[head+4'd3][7])
                    begin
                        id_jump_next = 2'd2;
                        head_next = head+4'd4;
                        data_out1_next = {40'b0,
                                          data[head+4'd1],
                                          data[head+4'd2],
                                          data[head+4'd3]};
                    end
                    
                    else if(total >= 5 && data[head+4'd4][7])
                    begin
                        id_jump_next = 2'd2;
                        head_next = head+4'd5;
                        data_out1_next = {32'b0,
                                          data[head+4'd1],
                                          data[head+4'd2],
                                          data[head+4'd3],
                                          data[head+4'd4]};
                    end
                    
                    else if(total >= 6 && data[head+4'd5][7])
                    begin
                        id_jump_next = 2'd2;
                        head_next = head+4'd6;
                        data_out1_next = {24'b0,
                                          data[head+4'd1],
                                          data[head+4'd2],
                                          data[head+4'd3],
                                          data[head+4'd4],
                                          data[head+4'd5]};
                    end
                    
                    else if(total >= 7 && data[head+4'd6][7])
                    begin
                        id_jump_next = 2'd2;
                        head_next = head+4'd7;
                        data_out1_next = {16'b0,
                                          data[head+4'd1],
                                          data[head+4'd2],
                                          data[head+4'd3],
                                          data[head+4'd4],
                                          data[head+4'd5],
                                          data[head+4'd6]};
                    end
                    
                    else if(total >= 8 && data[head+4'd7][7])
                    begin
                        id_jump_next = 2'd2;
                        head_next = head+4'd8;
                        data_out1_next = {8'b0,
                                          data[head+4'd1],
                                          data[head+4'd2],
                                          data[head+4'd3],
                                          data[head+4'd4],
                                          data[head+4'd5],
                                          data[head+4'd6],
                                          data[head+4'd7]};
                    end
                    else
                    begin
                        id_jump_next = 2'd1;
                        head_next = head+4'd1;
                        data_out1_next = 64'b0;
                    end
                end
                else if(total >= 2 && data[head+4'd1][7])
                begin
                    //head_next = head+4'd2;
                    data_out0_next = {48'b0,
                                      data[head],
                                      data[head+4'd1]};
                    if(total >= 3 && data[head+4'd2][7])
                    begin
                        id_jump_next = 2'd2;
                        head_next = head+4'd3;
                        data_out1_next = {56'b0,data[head+4'd2]};
                    end
                    
                    else if(total >= 4 && data[head+4'd3][7])
                    begin
                        id_jump_next = 2'd2;
                        head_next = head+4'd4;
                        data_out1_next = {48'b0,
                                          data[head+4'd2],
                                          data[head+4'd3]};
                    end
                    else if(total >= 5 && data[head+4'd4][7])
                    begin
                        id_jump_next = 2'd2;
                        head_next = head+4'd5;
                        data_out1_next = {40'b0,
                                          data[head+4'd2],
                                          data[head+4'd3],
                                          data[head+4'd4]};
                    end
                    
                    else if(total >= 6 && data[head+4'd5][7])
                    begin
                        id_jump_next = 2'd2;
                        head_next = head+4'd6;
                        data_out1_next = {32'b0,
                                          data[head+4'd2],
                                          data[head+4'd3],
                                          data[head+4'd4],
                                          data[head+4'd5]};
                    end
                    
                    else if(total >= 7 && data[head+4'd6][7])
                    begin
                        id_jump_next = 2'd2;
                        head_next = head+4'd7;
                        data_out1_next = {24'b0,
                                          data[head+4'd2],
                                          data[head+4'd3],
                                          data[head+4'd4],
                                          data[head+4'd5],
                                          data[head+4'd6]};
                    end
                    
                    else if(total >= 8 && data[head+4'd7][7])
                    begin
                        id_jump_next = 2'd2;
                        head_next = head+4'd8;
                        data_out1_next = {16'b0,
                                          data[head+4'd2],
                                          data[head+4'd3],
                                          data[head+4'd4],
                                          data[head+4'd5],
                                          data[head+4'd6],
                                          data[head+4'd7]};
                    end
                    else
                    begin
                        id_jump_next = 2'd1;
                        head_next = head+4'd2;
                        data_out1_next = 64'b0;
                    end
                end
                
                else if(total >= 3 && data[head+4'd2][7])
                begin
                    //head_next = head+4'd3;
                    data_out0_next = {40'b0,
                                      data[head],
                                      data[head+4'd1],
                                      data[head+4'd2]};
                    if(total >= 4 && data[head+4'd3][7])
                    begin
                        id_jump_next = 2'd2;
                        head_next = head+4'd4;
                        data_out1_next = {56'b0,data[head+4'd3]};
                    end
                    
                    else if(total >= 5 && data[head+4'd4][7])
                    begin
                        id_jump_next = 2'd2;
                        head_next = head+4'd5;
                        data_out1_next = {48'b0,
                                          data[head+4'd3],
                                          data[head+4'd4]};
                    end
                    
                    else if(total >= 6 && data[head+4'd5][7])
                    begin
                        id_jump_next = 2'd2;
                        head_next = head+4'd6;
                        data_out1_next = {40'b0,
                                          data[head+4'd3],
                                          data[head+4'd4],
                                          data[head+4'd5]};
                    end
                    
                    else if(total >= 7 && data[head+4'd6][7])
                    begin
                        id_jump_next = 2'd2;
                        head_next = head+4'd7;
                        data_out1_next = {32'b0,
                                          data[head+4'd3],
                                          data[head+4'd4],
                                          data[head+4'd5],
                                          data[head+4'd6]};
                    end
                    
                    else if(total >= 8 && data[head+4'd7][7])
                    begin
                        id_jump_next = 2'd2;
                        head_next = head+4'd8;
                        data_out1_next = {24'b0,
                                          data[head+4'd3],
                                          data[head+4'd4],
                                          data[head+4'd5],
                                          data[head+4'd6],
                                          data[head+4'd7]};
                    end
                    else
                    begin
                        id_jump_next = 2'd1;
                        head_next = head+4'd3;
                        data_out1_next = 64'b0;
                    end
                end
                
                else if(total >= 4 && data[head+4'd3][7])
                begin
                    //head_next = head+4'd4;
                    data_out0_next = {32'b0,
                                      data[head],
                                      data[head+4'd1],
                                      data[head+4'd2],
                                      data[head+4'd3]};
                    if(total >= 5 && data[head+4'd4][7])
                    begin
                        id_jump_next = 2'd2;
                        head_next = head+4'd5;
                        data_out1_next = {56'b0,data[head+4'd4]};
                    end
                    
                    else if(total >= 6 && data[head+4'd5][7])
                    begin
                        id_jump_next = 2'd2;
                        head_next = head+4'd6;
                        data_out1_next = {48'b0,
                                          data[head+4'd4],
                                          data[head+4'd5]};
                    end
                    
                    else if(total >= 7 && data[head+4'd6][7])
                    begin
                        id_jump_next = 2'd2;
                        head_next = head+4'd7;
                        data_out1_next = {40'b0,
                                          data[head+4'd4],
                                          data[head+4'd5],
                                          data[head+4'd6]};
                    end
                    
                    else if(total >= 8 && data[head+4'd7][7])
                    begin
                        id_jump_next = 2'd2;
                        head_next = head+4'd8;
                        data_out1_next = {32'b0,
                                          data[head+4'd4],
                                          data[head+4'd5],
                                          data[head+4'd6],
                                          data[head+4'd7]};
                    end
                    else
                    begin
                        id_jump_next = 2'd1;
                        head_next = head+4'd4;
                        data_out1_next = 64'b0;
                    end
                end
                
                else if(total >= 5 && data[head+4'd4][7])
                begin
                    //head_next = head+4'd5;
                    data_out0_next = {24'b0,
                                      data[head],
                                      data[head+4'd1],
                                      data[head+4'd2],
                                      data[head+4'd3],
                                      data[head+4'd4]};
                    if(total >= 6 && data[head+4'd5][7])
                    begin
                        id_jump_next = 2'd2;
                        head_next = head+4'd6;
                        data_out1_next = {56'b0,data[head+4'd5]};
                    end
                    
                    else if(total >= 7 && data[head+4'd6][7])
                    begin
                        id_jump_next = 2'd2;
                        head_next = head+4'd7;
                        data_out1_next = {48'b0,
                                          data[head+4'd5],
                                          data[head+4'd6]};
                    end
                    
                    else if(total >= 8 && data[head+4'd7][7])
                    begin
                        id_jump_next = 2'd2;
                        head_next = head+4'd8;
                        data_out1_next = {40'b0,
                                          data[head+4'd5],
                                          data[head+4'd6],
                                          data[head+4'd7]};
                    end
                    else
                    begin
                        id_jump_next = 2'd1;
                        head_next = head+4'd5;
                        data_out1_next = 64'b0;
                    end
                end
                
                else if(total >= 6 && data[head+4'd5][7])
                begin
                   // head_next = head+4'd6;
                    data_out0_next = {16'b0,
                                      data[head],
                                      data[head+4'd1],
                                      data[head+4'd2],
                                      data[head+4'd3],
                                      data[head+4'd4],
                                      data[head+4'd5]};
                    if(total >= 7 && data[head+4'd6][7])
                    begin
                        id_jump_next = 2'd2;
                        head_next = head+4'd7;
                        data_out1_next = {56'b0,data[head+4'd6]};
                    end
                    
                    else if(total >= 8 && data[head+4'd7][7])
                    begin
                        id_jump_next = 2'd2;
                        head_next = head+4'd8;
                        data_out1_next = {48'b0,
                                          data[head+4'd6],
                                          data[head+4'd7]};
                    end
                    else
                    begin
                        id_jump_next = 2'd1;
                        head_next = head+4'd6;
                        data_out1_next = 64'b0;
                    end
                end
                
                else if(total >= 7 && data[head+4'd6][7])
                begin
                    //head_next = head+4'd7;
                    data_out0_next = {8'b0,
                                      data[head],
                                      data[head+4'd1],
                                      data[head+4'd2],
                                      data[head+4'd3],
                                      data[head+4'd4],
                                      data[head+4'd5],
                                      data[head+4'd6]};
                    if(total >= 8 && data[head+4'd7][7])
                    begin
                        id_jump_next = 2'd2;
                        head_next = head+4'd8;
                        data_out1_next = {56'b0,data[head+4'd7]};
                    end
                    else
                    begin
                        id_jump_next = 2'd1;
                        head_next = head+4'd7;
                        data_out1_next = 64'b0;
                    end
                end
                
                else if(total >= 8)
                begin
                    head_next = head+4'd8;
                    data_out1_next = 64'b0;
                    if(data[head+4'd7][7])
                    begin
                        id_jump_next = 2'd1;
                        data_out0_next = {data[head],
                                          data[head+4'd1],
                                          data[head+4'd2],
                                          data[head+4'd3],
                                          data[head+4'd4],
                                          data[head+4'd5],
                                          data[head+4'd6],
                                          data[head+4'd7]};
                    end
                    else
                    begin
                        id_jump_next = 2'd0;
                        data_out0_next = 64'b0;
                    end
                end
                else
                begin
                    id_jump_next = 2'd0;
                    head_next = head;
                    data_out0_next = 64'b0;
                    data_out1_next = 64'b0;
                end
            end
            default:
            begin
                set=1'b0;
                id_jump_next = 2'd0;
                head_next = head;
                data_out0_next = 64'b0;
                data_out1_next = 64'b0;
                pmap_in[49:0] = 50'b0;
            end
        endcase
                
    end

    pmap2sel pmap2sel_0(
    .rst_n(rst_n),
    .clk(clk),
    .set(set),
    .pmap_in(pmap_in),
    .next(id_jump),
    .sel0(sel0),
    .sel1(sel1)
    );
endmodule
